package com.zkthink.ceres.order.service.impl;

import com.github.binarywang.wxpay.bean.request.WxPayRefundRequest;
import com.zkthink.base.R;
import com.zkthink.base.service.SuperServiceImpl;
import com.zkthink.ceres.common.constant.BizConstant;
import com.zkthink.ceres.member.entity.Member;
import com.zkthink.ceres.member.service.MemberService;
import com.zkthink.ceres.order.dao.*;
import com.zkthink.ceres.order.dto.*;
import com.zkthink.ceres.order.entity.*;
import com.zkthink.ceres.order.enums.ReturnGoodsStatusEnum;
import com.zkthink.ceres.order.enums.ReturnInterventionStatusEnum;
import com.zkthink.ceres.order.enums.ReturnMoneyStatusEnum;
import com.zkthink.ceres.order.enums.ReturnTypeEnum;
import com.zkthink.ceres.order.service.GoodsReturnActionHistoryService;
import com.zkthink.ceres.order.service.ReturnInterventionAdminService;
import com.zkthink.ceres.order.service.ReturnInterventionService;
import com.zkthink.ceres.pay.service.PayService;
import com.zkthink.context.BaseContextHandler;
import com.zkthink.database.mybatis.conditions.Wraps;
import com.zkthink.dozer.DozerUtils;
import com.zkthink.exception.code.ExceptionCode;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

import java.util.*;

/**
 * <p>
 * 业务实现类
 * 平台介入管理后台处理
 * </p>
 *
 * @author JustArgo
 * @date 2020-07-05
 */
@Slf4j
@AllArgsConstructor
@Service
public class ReturnInterventionAdminServiceImpl extends SuperServiceImpl<ReturnInterventionMapper, ReturnIntervention> implements ReturnInterventionAdminService {

    private MoneyReturnMapper moneyReturnMapper;

    private GoodsReturnMapper goodsReturnMapper;

    private OrderMapper orderMapper;

    private PayService payService;

    private MoneyReturnActionHistoryMapper moneyReturnActionHistoryMapper;

    private GoodsReturnActionHistoryMapper goodsReturnActionHistoryMapper;

    private DozerUtils dozerUtils;

    private MemberService memberService;

    private OrderProductMapper orderProductMapper;

    @Override
    public R<Boolean> auditReturnIntervention(AuditReturnInterventionDTO auditReturnInterventionDTO) {
        if(auditReturnInterventionDTO==null || auditReturnInterventionDTO.getId()==null){
            return R.fail(ExceptionCode.ILLEGALA_ARGUMENT_EX);
        }
        ReturnIntervention returnIntervention = baseMapper.selectById(auditReturnInterventionDTO.getId());
        if(returnIntervention==null){
            return R.fail(ExceptionCode.OPERATION_EX.getCode(),"介入对象不存在，无法审核");
        }
        if(returnIntervention.getStatus()!=ReturnInterventionStatusEnum.DEALING.getCode()){
            return R.fail(ExceptionCode.OPERATION_EX.getCode(),"该介入对象已审核过，无需再次审核");
        }
        Integer returnType = returnIntervention.getReturnType();
        String returnCode = returnIntervention.getReturnCode();
        if(returnType==ReturnTypeEnum.RETURN_MONEY.getCode()){
            MoneyReturn moneyReturn = moneyReturnMapper.selectOne(Wraps.<MoneyReturn>lbQ().eq(MoneyReturn::getReturnCode,returnCode));
            if(moneyReturn==null){
                return R.fail(ExceptionCode.NOT_FOUND.getCode(),"售后单不存在");
            }
            if(moneyReturn.getStatus()!= ReturnMoneyStatusEnum.AUDIT_REJECT.getCode()){
                return R.fail(ExceptionCode.OPERATION_EX.getCode(),"当前售后单不是被审核拒绝状态，不能审核平台介入");
            }

            if(auditReturnInterventionDTO.getStatus()==ReturnInterventionStatusEnum.AUDIT_PASS.getCode()){
                //直接退款给商家
                Map<String,Object> paramMap = new HashMap<String,Object>();
                paramMap.put("order_code",moneyReturn.getOrderCode());
                List<Order> orderList = orderMapper.selectByMap(paramMap);
                if(orderList.size()>0){
                    Order childOrder = orderList.get(0);
                    String outTradeNo = "";
                    Integer totalFee = null;

                    if(childOrder.getPrepayId()!=null && StringUtils.isNotBlank(childOrder.getPrepayId())){
                        outTradeNo = childOrder.getOrderCode();
                        totalFee = childOrder.getOrderSum().intValue();
                    }else{
                        Order parentOrder = orderMapper.selectByIdIgnoreTenant(childOrder.getParentId());
                        outTradeNo = parentOrder.getOrderCode();
                        totalFee = parentOrder.getOrderSum().intValue();
                    }

                    WxPayRefundRequest req = new WxPayRefundRequest();
                    req.setOutRefundNo(moneyReturn.getReturnCode());
                    req.setOutTradeNo(outTradeNo);
                    //订单总金额为支付的金额
                    req.setTotalFee(totalFee);
                    //只退订单的金额，不退运费
                    req.setRefundFee(moneyReturn.getApplySum().intValue());
                    try{
                        payService.refund(req);
                    }catch(Exception e){
                        log.error("refund fail:"+e.getMessage(),e);
                        return R.fail("平台介入审核通过，后台申请退款失败");
                    }
                }else{
                    return R.fail(ExceptionCode.OPERATION_EX.getCode(),"订单信息有误，审核失败");
                }

                MoneyReturnActionHistory moneyReturnActionHistory = new MoneyReturnActionHistory();
                moneyReturnActionHistory.setOrderId(moneyReturn.getOrderId());
                moneyReturnActionHistory.setReturnCode(moneyReturn.getReturnCode());
                moneyReturnActionHistory.setStatus(moneyReturn.getStatus());
                moneyReturnActionHistory.setActionNote("平台审核介入, 审核状态:审核通过, 备注:"+auditReturnInterventionDTO.getAuditRemark());
                moneyReturnActionHistoryMapper.insert(moneyReturnActionHistory);
            }else{
                moneyReturn.setStatus(ReturnMoneyStatusEnum.REFUND_FAIL.getCode());
                moneyReturnMapper.updateById(moneyReturn);

                MoneyReturnActionHistory moneyReturnActionHistory = new MoneyReturnActionHistory();
                moneyReturnActionHistory.setOrderId(moneyReturn.getOrderId());
                moneyReturnActionHistory.setReturnCode(moneyReturn.getReturnCode());
                moneyReturnActionHistory.setStatus(moneyReturn.getStatus());
                moneyReturnActionHistory.setActionNote("平台审核介入, 审核状态:审核不通过, 备注:"+auditReturnInterventionDTO.getAuditRemark());
                moneyReturnActionHistoryMapper.insert(moneyReturnActionHistory);
            }
        }else{
            GoodsReturn goodsReturn = goodsReturnMapper.selectOne(Wraps.<GoodsReturn>lbQ().eq(GoodsReturn::getReturnCode,returnCode));
            if(goodsReturn==null){
                return R.fail(ExceptionCode.NOT_FOUND.getCode(),"售后单不存在");
            }
            if(goodsReturn.getStatus()!= ReturnGoodsStatusEnum.AUDIT_REJECT.getCode()){
                return R.fail(ExceptionCode.OPERATION_EX.getCode(),"当前售后单不是被审核拒绝状态，不能申请平台介入");
            }

            if(auditReturnInterventionDTO.getStatus()==ReturnInterventionStatusEnum.AUDIT_PASS.getCode()){
                goodsReturn.setStatus(ReturnGoodsStatusEnum.AUDIT_PASS.getCode());
                goodsReturnMapper.updateById(goodsReturn);
            }else{
                goodsReturn.setStatus(ReturnGoodsStatusEnum.REFUND_FAIL.getCode());
                goodsReturnMapper.updateById(goodsReturn);

                GoodsReturnActionHistory goodsReturnActionHistory = new GoodsReturnActionHistory();
                goodsReturnActionHistory.setOrderId(goodsReturn.getOrderId());
                goodsReturnActionHistory.setReturnCode(goodsReturn.getReturnCode());
                goodsReturnActionHistory.setStatus(goodsReturn.getStatus());
                goodsReturnActionHistory.setActionNote("平台审核介入, 审核状态:审核不通过, 备注:"+auditReturnInterventionDTO.getAuditRemark());
                goodsReturnActionHistoryMapper.insert(goodsReturnActionHistory);
            }
        }

        return R.success();
    }

    @Override
    public R<ReturnInterventionPageDTO> findReturnInterventionList(QueryReturnInterventionDTO queryDTO) {
        if(queryDTO==null){
            return R.fail(ExceptionCode.ILLEGALA_ARGUMENT_EX);
        }
        if(queryDTO.getPageIndex()==null || queryDTO.getPageIndex()<1){
            queryDTO.setPageIndex(1);
        }
        if(queryDTO.getPageSize()==null || queryDTO.getPageSize()<1 || queryDTO.getPageSize()>100){
            queryDTO.setPageSize(10);
        }
        Integer start = (queryDTO.getPageIndex() - 1) * queryDTO.getPageSize();
        queryDTO.setStart(start);
        List<ReturnInterventionDTO> dtoList = baseMapper.findReturnInterventionList(queryDTO);
        for(ReturnInterventionDTO dto:dtoList){
            Integer returnType = dto.getReturnType();
            String returnCode = dto.getReturnCode();
            if (returnType == ReturnTypeEnum.RETURN_MONEY.getCode()) {
                MoneyReturn moneyReturn = moneyReturnMapper.selectOne(Wraps.<MoneyReturn>lbQ().eq(MoneyReturn::getReturnCode, returnCode));
                if (moneyReturn != null) {
                    String[] ops = moneyReturn.getOrderProductIds().split(",");
                    if (ops != null) {
                        dto.setReturnProductCount(ops.length);
                    }
                    dto.setApplySum(moneyReturn.getApplySum());
                }
            } else {
                GoodsReturn goodsReturn = goodsReturnMapper.selectOne(Wraps.<GoodsReturn>lbQ().eq(GoodsReturn::getReturnCode, returnCode));
                if (goodsReturn != null) {
                    String[] ops = goodsReturn.getOrderProductIds().split(",");
                    if (ops != null) {
                        dto.setReturnProductCount(ops.length);
                    }
                    dto.setApplySum(goodsReturn.getApplySum());
                }
            }
        }
        Integer total = baseMapper.findReturnInterventionListCount(queryDTO);
        ReturnInterventionPageDTO pageDTO = new ReturnInterventionPageDTO();
        pageDTO.setTotal(total);
        pageDTO.setReturnInterventionDTOList(dtoList);
        return R.success(pageDTO);
    }

    @Override
    public R<ReturnInterventionDetailDTO> getReturnInterventionDetail(Long id) {
        if(id==null){
            return R.fail(ExceptionCode.ILLEGALA_ARGUMENT_EX);
        }
        ReturnIntervention returnIntervention = baseMapper.selectById(id);
        if(returnIntervention==null){
            return R.fail(ExceptionCode.ILLEGALA_ARGUMENT_EX.getCode(),"平台介入不存在");
        }
        String orderCode = returnIntervention.getOrderCode();
        Order order = orderMapper.selectOne(Wraps.<Order>lbQ().eq(Order::getOrderCode,orderCode));
        ReturnInterventionDetailDTO interventionDetailDTO = dozerUtils.map(order,ReturnInterventionDetailDTO.class);

        String tenantCode = order.getTenantCode();
        BaseContextHandler.setTenant(null);
        Member member = memberService.getById(order.getMid());
        if(member!=null){
            interventionDetailDTO.setMemberAccount(member.getNickname());
        }
        BaseContextHandler.setTenant(tenantCode);

        Integer returnType = returnIntervention.getReturnType();
        String returnCode = returnIntervention.getReturnCode();

        List<Long> opList = new ArrayList<Long>();
        if (returnType == ReturnTypeEnum.RETURN_MONEY.getCode()) {
            MoneyReturn moneyReturn = moneyReturnMapper.selectOne(Wraps.<MoneyReturn>lbQ().eq(MoneyReturn::getReturnCode, returnCode));
            if (moneyReturn != null) {
                String[] ops = moneyReturn.getOrderProductIds().split(",");
                for(String opId:ops){
                    opList.add(Long.valueOf(opId));
                }
            }
            interventionDetailDTO.setApplySum(moneyReturn.getApplySum());
            List<MoneyReturnActionHistory> moneyReturnActionHistoryList = moneyReturnActionHistoryMapper
                        .selectList(Wraps.<MoneyReturnActionHistory>lbQ().eq(MoneyReturnActionHistory::getReturnCode,returnCode)
                            .eq(MoneyReturnActionHistory::getIsDelete,0)
                            .orderByDesc(MoneyReturnActionHistory::getCreateTime));
            interventionDetailDTO.setMoneyReturnActionHistoryList(moneyReturnActionHistoryList);
        } else {
            GoodsReturn goodsReturn = goodsReturnMapper.selectOne(Wraps.<GoodsReturn>lbQ().eq(GoodsReturn::getReturnCode, returnCode));
            if (goodsReturn != null) {
                String[] ops = goodsReturn.getOrderProductIds().split(",");
                for(String opId:ops){
                    opList.add(Long.valueOf(opId));
                }
            }
            interventionDetailDTO.setApplySum(goodsReturn.getApplySum());
            List<GoodsReturnActionHistory> goodsReturnActionHistoryList = goodsReturnActionHistoryMapper
                    .selectList(Wraps.<GoodsReturnActionHistory>lbQ().eq(GoodsReturnActionHistory::getReturnCode, returnCode)
                        .eq(GoodsReturnActionHistory::getIsDelete,0)
                        .orderByDesc(GoodsReturnActionHistory::getCreateTime));
            interventionDetailDTO.setGoodsReturnActionHistoryList(goodsReturnActionHistoryList);
        }

        List<OrderProduct> orderProductList = orderProductMapper.selectList(Wraps.<OrderProduct>lbQ().eq(OrderProduct::getOrderId,order.getId()).in(OrderProduct::getId,opList));
        List<OrderProductDTO> orderProductDTOList = dozerUtils.mapList(orderProductList,OrderProductDTO.class);
        interventionDetailDTO.setOrderProductDTOList(orderProductDTOList);

        interventionDetailDTO.setReturnIntervention(returnIntervention);

        return R.success(interventionDetailDTO);
    }
}
